#include <stdio.h>
#include <windows.h>

#define TRUE 1
#define FALSE 0

#define ELEM_INITIAL 0

	typedef int elemType;

	typedef struct QNode{
		elemType data;
		struct QNode* next;
	}QNode;

	typedef struct {
		QNode* front;
		QNode* rear;
	}LinkQueue;

	int InitQueue(LinkQueue* Q)
	{
		QNode* e;

		e = (QNode*) malloc(sizeof QNode);
		e->data = ELEM_INITIAL;
		e->next = NULL;

		Q->rear = Q->front = e;

		return TRUE;
	}
	
	int QueueEmpty(LinkQueue Q)
	{
		if (Q.front == Q.rear) return TRUE;
		else return FALSE;
	}

	int QueueLength(LinkQueue Q)
	{
		int len = 0;

		if (!Q.front) return FALSE;

		QNode* temp = Q.front->next;

		while(temp)
		{
			temp = temp->next;
			len++;
		}

		return len;
	}

	int ClearQueue(LinkQueue* Q)
	{
		QNode* preP,* nextP;

		preP = nextP = Q->front->next;

		while(preP)
		{
			nextP = preP->next;
			free(preP);
			preP = nextP;
		}

		Q->front->next = NULL;
		Q->rear = Q->front;

		return TRUE;
	}

	int DestroyQueue(LinkQueue* Q)
	{
		ClearQueue(Q);

		free(Q->front);

		Q->front = NULL;
		Q->rear = NULL;

		return TRUE;
	}

	int GetHead(LinkQueue Q, elemType* e)
	{
		if (!QueueEmpty(Q)) return FALSE;

		*e = Q.front->next->data;

		return TRUE;
	}

	int EnQueue(LinkQueue* Q, elemType e)
	{
		QNode* temp = (QNode*) malloc(sizeof QNode);
		if (!temp) return FALSE;

		temp->data = e;
		temp->next = NULL;

		Q->rear->next = temp;
		Q->rear = Q->rear->next;

		return TRUE;
	}

	int DeQueue(LinkQueue* Q, elemType* e)
	{
		QNode* temp = Q->front->next;
		if (QueueEmpty(*Q)) return FALSE;
		
		*e = temp->data;
		Q->front->next = Q->front->next->next;
		free(temp);

		return TRUE;
	}

	int _show(elemType* e)
	{
		printf("Value:%d\n",*e);

		return TRUE;
	}

	int QueueTraverse(LinkQueue Q, int (*visit)(elemType* e) = _show)
	{
		QNode* temp = Q.front->next;
		if (QueueEmpty(Q)) return FALSE;

		while(temp)
		{
			visit(&temp->data);
			temp = temp->next;
		}

		return TRUE;
	}

	int _showImg(LinkQueue Q)
	{
		QNode* temp;
 		if (QueueEmpty(Q)) return FALSE;

		temp = Q.front->next;

		printf("\t|     |\n");
		while(temp)
		{
			printf("\t|%5d|\n", temp->data);
			temp = temp->next;
		}
		printf("\t|     |\n");

		return TRUE;
	}

	int _showStatus(LinkQueue Q)
	{
		printf("\nLength:\t%d\nFront:\t%X\nReae:\t%X\n\n",QueueLength(Q), Q.front, Q.rear);

		if (_showImg(Q)) printf("\n");

		return TRUE;
	}

	int main()
	{
		LinkQueue examQ;
		elemType examE;
		int i=10;

		printf("##Queue will be initialed.\n");
		InitQueue(&examQ);
		_showStatus(examQ);

		printf("##Insert new element into Queue.\n");
		while(i-- != 1) EnQueue(&examQ, i);
		_showStatus(examQ);

		printf("##Destroy the Queue.\n");
		DestroyQueue(&examQ);
		_showStatus(examQ);

/*		printf("##Try insert new element to a bad Queue.\n");
		EnQueue(&examQ, 123);
		_showStatus(examQ);
*/
		printf("##Initial the track again.\n");
		InitQueue(&examQ);
		_showStatus(examQ);

		printf("##Insert new element again.\n");
		while(++i != 5) EnQueue(&examQ, i);
		_showStatus(examQ);
		
		printf("##traverse every element.\n\n");
		QueueTraverse(examQ);

		printf("##Delete existed element.\n");
		while (++i != 8)
		{
			DeQueue(&examQ, &examE);
			printf("Value '%d' has been poped.\n", examE);
		}
		_showStatus(examQ);

		DestroyQueue(&examQ);
		system("pause");
	}
